//
//  BKWebViewVC.swift
//  TestDemoSwift
//
//  Created by 王锦发 on 2020/3/28.
//  Copyright © 2020 WJF. All rights reserved.
//

import UIKit
import WebKit
import SystemConfiguration
import HandyJSON
import SwiftyJSON

struct WebViewKey {
    static let progress = "estimatedProgress"
    static let title = "title"
}

protocol EnumeratableEnum {
    static var allValues: [Self] { get }
}

/** H5调用App的交互方法名 */
enum BKWebViewJSName: String {
    case popToRootWindow
    case goBack
    case openNewWindow
    case closeWindow
}

/** App调用H5的方法名 */
enum EvaluateJSMethod: String {
    case pageReload // 刷新当前页
    case sessionStorageClear = "sessionStorage.clear" // 清空session
}

extension BKWebViewJSName: EnumeratableEnum {
    static var allValues: [BKWebViewJSName] {
        return [
            .popToRootWindow, .goBack, .openNewWindow, .closeWindow
        ]
    }
}

/** 防止添加js方法时引起的内存泄漏*/
class BKWebViewScriptMessageHanlder: NSObject,WKScriptMessageHandler {
    
    deinit {
        PPP("BKWebViewScriptMessageHanlder is deinit")
    }
    
    weak var delegate: WKScriptMessageHandler?
    
    init(delegate: WKScriptMessageHandler?) {
        self.delegate = delegate
        super.init()
        
    }
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        self.delegate?.userContentController(userContentController, didReceive: message)
    }
    
}

protocol BKWebViewDelegate: NSObjectProtocol {
    /** JS交互时JS调用原生方法时收到的消息，以及内容*/
    func runJavaScriptReceiveMessage(message: WKScriptMessage)
}

extension BKWebViewDelegate {
    func runJavaScriptReceiveMessage(message: WKScriptMessage) { }
}

class BKWebViewVC: BaseVC {
    
    // MARK: - deinit
    deinit {
        /** 移除js方法，防止内存泄漏*/
        if webView != nil {
            webView.removeObserver(self, forKeyPath: WebViewKey.progress)
            webView.removeObserver(self, forKeyPath: WebViewKey.title)
            /** 修复pop返回可能会引起的崩溃*/
            webView.scrollView.delegate = nil
        }
        
        self.removeNOC()
        self.removeScriptMessageHandler()
        BKWebViewPool.shared.tryCompactWeakHolders()
        PPP("[\(NSStringFromClass(type(of: self)))]>>>已被释放")
    }
    
    enum H5Type: Int {
        case `default`
    }
    
    enum WebType {
        case H5
        case APP(AppMark)
        
        enum AppMark {
            case `default`
        }
    }
    
    /** 网页视图*/
    public var webView: BKWebView!
    /** 代理*/
    public weak var delegate: BKWebViewDelegate?
    /** JS交互时JS调用原生方法时收到的消息，以及内容*/
    public var runJavaScriptReceiveMessageBlock: ((WKScriptMessage) -> Void)?
    /** 自动改变标题，根据url的标题*/
    public var autoChangeTitle: Bool = true
    /** 自定义标题*/
    public var customNaviTitle: String = ""
    /** 是否下拉重新加载*/
    public var canDownRefresh: Bool = true
    /** 当前网页加载地址*/
    public var urlString: String = ""
    /** 标记类型*/
    public var webType: WebType = .APP(.default)
    
    /** 自定义的scheme*/
    private var url_scheme: String = ""
    /** 网页来源标记标签*/
    private var memoLabel: UILabel!
    /** 进度条*/
    private var progressView: BKGradientProgressView!
    /** 容器视图*/
    private var containerView: UIScrollView!
    /** js交互的方法名集合*/
    private var scriptMessageHandlerNames = [BKWebViewJSName]()
    /** h5网页类型*/
    private var h5Type: H5Type = .default
    /** wkwebview高度*/
    private var webViewHeight: CGFloat = 0.0
    /** 是否隐藏系统NavigationBar*/
    private var naviBarHidden: Bool = false
    /** 标记是否已经展示过网络开小差*/
    private var isShowedNetWorkError: Bool = false
    
    // MARK: - convenience init
    /// 初始化WKWebView控制器
    ///
    /// - Parameters:
    ///   - urlString: 当前网页加载地址
    ///   - type: 标记从什么类型跳转打开
    convenience init(with urlString: String, type: WebType = .APP(.default)) {
        self.init()
        self.urlString = urlString
        self.webType = type
        
    }
    
    // MARK: Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .lightWhiteDark27
        
        self.loadUI()
        self.showLeftBarButtonItem()
        self.updateWebViewLayout()
        
        // 监听当前网络状态
        NetStatusTool.shared.monitor { [weak self] (status) in
            switch status {
            case .wifi, .cellular:
                self?.hideNetWorkErrorView()
                self?.loadURL()
            default:
                if self?.isShowedNetWorkError == true {
                    HintTool.toast(status.rawValue)
                } else {
                    self?.showNetWorkErrorView()
                }
            }
        }
        
        self.addNOC()
        
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigation.bar.isHidden = naviBarHidden
        // 可能白屏
        if webView.title == nil {
            webView.reload()
        }
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let canPop: Bool
        switch webType {
        case .H5: canPop = false
        case .APP: canPop = true
        }
        self.bk_setPopSwipe(canPop)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.bk_setPopSwipe(true)
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        navigation.bar.isHidden = false
    }
    
    // MARK: - lazy
    lazy var vm: BaseViewModel = {
        let vm = BaseViewModel()
        return vm
    }()
    
    private lazy var refreshControl: UIRefreshControl = {
        let refresh = UIRefreshControl()
        refresh.addTarget(self, action: #selector(wkWebViewReload), for: .valueChanged)
        return refresh
    }()
    
    private lazy var backBarButtonItem: UIBarButtonItem = {
        let barItem = UIBarButtonItem(image: .ArrowFork.icon_leftArrow, style: .done, target: self, action: #selector(wkWebViewGoback))
        return barItem
    }()
    
    private lazy var closeBarButtonItem: UIBarButtonItem = {
        let barItem = UIBarButtonItem(image: .ArrowFork.icon_fork, style: .done, target: self, action: #selector(goBack))
        return barItem
    }()
    
    private lazy var netWorkErrorImageView: UIImageView = {
        let iv = UIImageView(image: UIImage(named: "icon_networkerror"))
        return iv
    }()
    
    private lazy var netWorkErrorLabel: UILabel = {
        let label = self.bk_addLabel(text: "网络开小差啦\n无法连接到网络", bgColor: .clear, textColor: ColorDef.light139, align: .center)
        return label
    }()
    
    // MARK: - 加载UI
    private func loadUI() {
        
        containerView = UIScrollView(frame: view.bounds)
        containerView.backgroundColor = .lightWhiteDark27
        containerView.showsVerticalScrollIndicator = false
        containerView.showsHorizontalScrollIndicator = false
        containerView.isScrollEnabled = false
        view.addSubview(containerView)
        
        webView = BKWebViewPool.shared.getReusedWebView(for: self)
        webView.frame = kCGRect(0, 0, kScreenWidth, kScreenHeight-kNavigationBarHeight)
        self.addScriptMessageHandler()
        
        if #available(iOS 11.0, *) {
            webView.scrollView.contentInsetAdjustmentBehavior = .never
        } else {
            self.automaticallyAdjustsScrollViewInsets = false
        }
        
        webView.uiDelegate = self
        webView.navigationDelegate = self
        webView.isExclusiveTouch = false
        webView.scrollView.delegate = self
        webView.scrollView.decelerationRate = .normal
        webView.scrollView.bouncesZoom = false
        webView.allowsBackForwardNavigationGestures = true
        if canDownRefresh {
            webView.scrollView.refreshControl = refreshControl
        }
        
        webView.addObserver(self, forKeyPath: WebViewKey.progress, options: .new, context: nil)
        webView.addObserver(self, forKeyPath: WebViewKey.title, options: .new, context: nil)
        containerView.addSubview(webView)
        
        memoLabel = UILabel(frame: CGRect(x: 0, y: 20, width: view.frame.width, height: 20))
        memoLabel.textAlignment = .center
        memoLabel.font = .systemFont(ofSize: 12)
        memoLabel.textColor = .gray
        memoLabel.alpha = 0.0 // 1.0
        containerView.addSubview(memoLabel)
        
        progressView = BKGradientProgressView(frame: kCGRect(0, 0, view.frame.width, 3))
        progressView.backgroundColor = .clear
        progressView.progressCornerRadius = 1.5
        progressView.progressColors = [.blue]
        progressView.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        progressView.alpha = 0.0
        containerView.addSubview(progressView)
        
    }
    
    // MARK: - KVO监听
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == WebViewKey.progress {
            progressView.alpha = 1.0
            progressView.setProgress(Float(webView.estimatedProgress), animated: true)
            if webView.estimatedProgress >= 1.0 {
                UIView.animate(withDuration: 0.3, delay: 0.3, options: .curveEaseOut, animations: { [weak self] in
                    guard let strongSelf = self else { return }
                    strongSelf.progressView.alpha = 0.0
                }) { [weak self] (_) in
                    guard let strongSelf = self else { return }
                    strongSelf.progressView.setProgress(0, animated: false)
                }
            }
        } else if keyPath == WebViewKey.title {
            if customNaviTitle.isValid {
                navigation.item.title = customNaviTitle
            } else {
                let _title = webView.title ?? ""
                if _title.contains("jpg") || _title.contains("png") {
                    navigation.item.title = _title.prefixLower(range: ".")
                } else {
                    navigation.item.title = webView.title
                }
            }
        } else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
    
}

// MARK: - 通知
extension BKWebViewVC {
    
    private func addNOC() {
        
    }
    
    private func removeNOC() {
        
    }
    
}

// MARK: - Selector
extension BKWebViewVC {
    
    @objc private func reloadPage() {
        self.callJSMethod(by: .pageReload)
    }
    
    @objc private func sessionStorageClear() {
        let backList = webView.backForwardList.backList
        if !backList.isEmpty, let item = backList.first {
            webView.go(to: item)
        } else if webView.canGoBack {
            while webView.canGoBack {
                webView.goBack()
            }
        }
        self.callJSMethod(by: .sessionStorageClear)
        webView.reload()
    }
    
    @objc func wkWebViewReload() {
        webView.reload()
        if refreshControl.isRefreshing {
            TaskTool.delay(1.0) {
                self.refreshControl.endRefreshing()
            }
        }
    }
    
    @objc func wkWebViewGoback() {
        self.webGoBack()
    }
    
}

// MARK: - Private
extension BKWebViewVC {
    
    private func showNetWorkErrorView() {
        containerView.addSubviews([netWorkErrorImageView, netWorkErrorLabel])
        containerView.bk_bringSubviewsToFront([netWorkErrorImageView, netWorkErrorLabel])
        netWorkErrorImageView.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.centerY.equalToSuperview().offset(-kStatusBarHeight)
        }
        netWorkErrorLabel.snp.makeConstraints { make in
            make.top.equalTo(netWorkErrorImageView.snp.bottom).offset(15)
            make.centerX.equalToSuperview()
        }
        isShowedNetWorkError = true
    }
    
    private func hideNetWorkErrorView() {
        if containerView.subviews.contains([netWorkErrorImageView, netWorkErrorLabel]) {
            netWorkErrorImageView.removeFromSuperview()
            netWorkErrorLabel.removeFromSuperview()
        }
    }
    
    private func addScriptMessageHandler() {
        let jsNames = BKWebViewJSName.allValues
//        userContentController = WKUserContentController()
        let msgHandler = BKWebViewScriptMessageHanlder(delegate: self)
        scriptMessageHandlerNames += jsNames
        jsNames.forEach { (name) in
            webView.configuration.userContentController.add(msgHandler, name: name.rawValue)
//            userContentController.add(msgHandler, name: name.rawValue)
        }
    }
    
    private func removeScriptMessageHandler() {
        for script in scriptMessageHandlerNames {
            webView.configuration.userContentController.removeScriptMessageHandler(forName: script.rawValue)
        }
    }
    
    private func setWebviewMemo(_ memo: String?) {
        guard let promtMessage = memo, promtMessage.count > 0 else { return }
        if memoLabel != nil {
            memoLabel.text = "此网页由 "+promtMessage+" 提供"
        }
    }
    
    private func showLeftBarButtonItem() {
        if webView.canGoBack {
            navigation.item.leftBarButtonItems = [backBarButtonItem, closeBarButtonItem]
        } else {
            navigation.item.leftBarButtonItem = backBarButtonItem
        }
    }
    
    private func updateWebViewLayout() {
        guard urlString.count > 0 else { return }
        
        let height: CGFloat
        switch h5Type {
        case .default:
            naviBarHidden = false
            height = kScreenHeight-kNavigationBarHeight
        }
        webView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: height)
    }
    
    // MARK: - 加载URL
    private func loadURL() {
        guard let url = URL(string: urlString) else { return }
        if webView.isLoading {
            webView.stopLoading()
        }
        self.loadReq(url, h5Type)
    }
    
    private func loadReq(_ url: URL, _ type: H5Type) {
        
        /**
         * .useProtocolCachePolicy                 ---> 默认的cache policy,使用Protocol协议定义
         * .reloadIgnoringCacheData                ---> 忽略缓存直接从原始地址下载
         * .returnCacheDataDontLoad                ---> 只使用cache数据,如果不存在cache,请求失败；用于没有建立网络连接离线模式
         * .returnCacheDataElseLoad                ---> 只有在cache中不存在data时才从原始地址下载
         * .reloadIgnoringLocalAndRemoteCacheData  ---> 忽略本地和远程的缓存数据,直接从原始地址下载
         * .reloadRevalidatingCacheData            ---> 验证本地数据与远程数据是否相同，如果不同则下载远程数据，否则使用本地数据
         */
        
        switch type {
        case .default:
            let urlReq = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 20.0)
            webView.load(urlReq)
        default:
            /**
             * ETag：服务器验证令牌，文件内容hash。
             * Last-Modified：响应头标识了资源的最后修改时间。
             * If-None-Match：比较ETag是否不一致。
             * If-Modified-Since：比较资源最后修改的时间是否一致
             */
            var req = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 20.0)
            // 判断是否有更新,只请求responseHeader
            req.httpMethod = "HEAD"
            // 获取记录的response headers
            let cacheHeaders = UserDefaults.standard.object(forKey: url.absoluteString) as? [String: Any]
            // 设置request headers
            if cacheHeaders != nil {
                if let etag = cacheHeaders?["Etag"] as? String {
                    req.setValue(etag, forHTTPHeaderField: "If-None-Match")
                }
                if let lastModified = cacheHeaders?["Last-Modified"] as? String {
                    req.setValue(lastModified, forHTTPHeaderField: "If-Modified-Since")
                }
            }
            
            URLSession.shared.dataTask(with: req) { (data, resp, error) in
                guard let httpResp = resp as? HTTPURLResponse else { return }
                PPP("WKWebView StatusCode == \(httpResp.statusCode)")
                if httpResp.statusCode == 304 || httpResp.statusCode == 0 {
                    // 如果状态码为304或者0(网络不通)，则设置request的缓存策略为读取本地缓存
                    req.cachePolicy = .returnCacheDataElseLoad
                } else {
                    // 如果状态码为200，则保存本次的response headers，并设置request的缓存策略为忽略本地缓存，重新请求数据
                    UserDefaults.standard.set(httpResp.allHeaderFields, forKey: req.url?.absoluteString ?? "")
                    req.cachePolicy = .reloadIgnoringLocalCacheData
                }
                DispatchQueue.main.async {
                    req.httpMethod = "GET"
                    self.webView.load(req)
                }
            }.resume()
        }
        
    }
    
}

// MARK: - Public
extension BKWebViewVC {
    
    static func initWithURLString(_ urlString: String) -> BKWebViewVC {
        let webView = BKWebViewVC()
        webView.urlString = urlString
        return webView
    }
    
    func callJSMethod(by jsString: EvaluateJSMethod, _ completion: ((Any?, Error?) -> Void)? = nil) {
        let js = "\(jsString.rawValue)()"
        webView.evaluateJavaScript(js, completionHandler: completion)
    }
    
    /** 控制WebView的侧滑返回*/
    func allowBackWithGestures(_ isAllow: Bool) {
        webView.allowsBackForwardNavigationGestures = isAllow
    }
    
    /** 复用WKWebView需要清除历史记录*/
    func clearWkWebViewHistory() {
        webView.evaluateJavaScript("document.body.innerHTML = '';", completionHandler: nil)
    }
    
}

// MARK: - 交互
extension BKWebViewVC {
    
    /// 处理与JS交互的方法
    private func handleWKScriptMessage(name: String, body: Any, completion: ((String?) -> Void)? = nil) {
        let jsName = BKWebViewJSName(rawValue: name)
        switch jsName {
        case .popToRootWindow:   self.popToRootWindow()
        case .goBack:            self.webGoBack()
        case .openNewWindow:     self.openNewWindow(body as! String)
        case .closeWindow:       self.closeWindow(index: body as? Int)
        default: break
        }
        completion?(nil)
    }
    
}

// MARK: - WebView JS交互
extension BKWebViewVC: WKScriptMessageHandler {
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        self.delegate?.runJavaScriptReceiveMessage(message: message)
        self.runJavaScriptReceiveMessageBlock?(message)
        
        // message.name  方法名
        // message.body  参数值
        PPP("\n方法名name: \(message.name);\n参数值body: \(message.body)")
        self.handleWKScriptMessage(name: message.name, body: message.body)
    }
    
    func popToRootWindow() {
        VisibleNaviCtrl?.popToRootViewController(animated: true)
    }
    
    func webGoBack() {
        if webView.canGoBack && BKWebViewPool.shared.justOneVisibleWebView {
            webView.goBack()
        } else if webView.canGoBack {
            if webView.backForwardList.backList.count == 2 {
                self.closeWindow(index: -2)
            } else {
                webView.goBack()
            }
        } else {
            self.clearWkWebViewHistory()
            self.callJSMethod(by: .sessionStorageClear)
            self.bk_autoBack()
        }
    }
    
    func openNewWindow(_ url: String) {
        let vc = BKWebViewVC.initWithURLString(url)
        self.navigationController?.pushViewController(vc)
    }
    
    func closeWindow(index: Int?) {
        guard index != nil, let viewCtrls = self.navigationController?.viewControllers else {
            self.clearWkWebViewHistory()
            self.callJSMethod(by: .sessionStorageClear)
            self.bk_autoBack()
            return
        }
        if viewCtrls.count > 1 {
            if let _index = index, let item = webView.backForwardList.item(at: _index) {
                webView.go(to: item)
            } else {
                if webView.canGoBack {
                    webView.goBack()
                } else {
                    self.clearWkWebViewHistory()
                    self.callJSMethod(by: .sessionStorageClear)
                    self.bk_autoBack()
                }
            }
        } else {
            guard let _index = index else {
                if webView.canGoBack {
                    webView.goBack()
                }
                return
            }
            if webView.canGoBack && index == -1 {
                webView.goBack()
            } else {
                if webView.backForwardList.backList.count != abs(_index) && webView.canGoBack {
                    webView.goBack()
                } else {
                    if let item = webView.backForwardList.item(at: _index) {
                        webView.go(to: item)
                    }
                }
            }
        }
    }
    
}

// MARK: - WXApiManagerDelegate代理
//extension BKWebViewVC: WXApiManagerDelegate {
//
//    func handleOpen(url: URL) {
//        var urlStr = url.absoluteString
//        urlStr = urlStr.replacingOccurrences(of: url_scheme, with: "")
//        PPP("urlStr: \(urlStr)")
//        webView.loadWithURL(urlStr)
//    }
//
//}

// MARK: - WKNavigationDelegate,WKUIDelegate代理
extension BKWebViewVC: WKNavigationDelegate,WKUIDelegate {
    
    // 在发送请求之前,决定是否跳转
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        decisionHandler(.allow)
    }
    
    // 在收到响应后,决定是否跳转
    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        
        guard let httpResp = navigationResponse.response as? HTTPURLResponse else {
            decisionHandler(.allow)
            return
        }
        let policy: WKNavigationResponsePolicy = httpResp.statusCode == 200 ? .allow : .cancel
        decisionHandler(policy)
        
    }
    
    // 接收到服务器跳转请求之后再执行
    func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        
    }
    
    // 当webView需要响应身份验证时调用(如需验证服务器证书)
    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        
        let authenticationMethod = challenge.protectionSpace.authenticationMethod
        if authenticationMethod == NSURLAuthenticationMethodServerTrust {
            guard let secTrust = challenge.protectionSpace.serverTrust else { return }
            let credential = URLCredential(trust: secTrust)
            completionHandler(.useCredential, credential)
        }
        
    }
    
    // 创建一个新的WebView
    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        
        guard let isMainFrame = navigationAction.targetFrame?.isMainFrame else { return nil }
        if !isMainFrame {
            webView.load(navigationAction.request)
        }
        return nil
        
    }
    
    // 页面开始加载时调用
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        self.setWebviewMemo(webView.url?.host)
    }
    
    // 当内容开始返回时调用
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        
    }
    
    // 页面加载完成之后调用
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        if autoChangeTitle {
            self.navigation.item.title = webView.title
        }
        if customNaviTitle.isValid {
            self.navigation.item.title = customNaviTitle
        }
        webView.evaluateJavaScript("document.body.scrollHeight") { [weak self] (result, error) in
            self?.webViewHeight = CGFloat((result as? NSNumber)?.doubleValue ?? 0.0)
            PPP("WKWebView高度: \(self?.webViewHeight ?? 0.0)")
        }
    }
    
    // 页面加载失败时调用
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        
    }
    
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        
    }
    
    // 当WKWebView总体内存占用过大即将白屏的时候
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        webView.reload()
    }
    
    // MARK: - 警告框Alert
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        
        let alert = UIAlertController(title: "", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_) in
            completionHandler()
        }))
        self.present(alert, animated: true)
        
    }
    
    // MARK: - 确认框Confirm
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
        
        let alert = UIAlertController(title: "", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) in
            completionHandler(true)
        }))
        alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (_) in
            completionHandler(false)
        }))
        self.present(alert, animated: true)
        
    }
    
    // MARK: - 输入框Prompt
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
        
        // 根据prompt进行判断执行相应的方法，defaultText为参数值，completionHandler为给js的回调
        PPP("参数值defaultText: \(defaultText ?? ""); 方法名prompt: \(prompt)")
        self.handleWKScriptMessage(name: prompt, body: defaultText as Any) { (_callback) in
            completionHandler(_callback)
        }
        
    }
    
}

// MARK: - UIScrollViewDelegate代理
extension BKWebViewVC: UIScrollViewDelegate {
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let offsetY = scrollView.contentOffset.y
        guard memoLabel != nil else { return }
        if offsetY < 0 {
            if fabsf(Float(offsetY)) > 50 {
                let alpha = (fabsf(Float(offsetY)) - 50) / 100.00
                if alpha >= 1.0 {
                    memoLabel.alpha = 1.0
                } else {
                    memoLabel.alpha = CGFloat(alpha)
                }
            } else {
                memoLabel.alpha = 0.0
            }
        } else {
            memoLabel.alpha = 0.0
        }
    }
    
}
